﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Tradex.Collections.Generic {
    
    public class PagedCache<T> {

        public PagedCache() {
            _CachePages = new List<T[]>(256);
        }

        List<T[]> _CachePages;

        public T this[int index] {
            get {
                IndexParts realIndex = new IndexParts() {
                    FullValue = index
                };
                int firstindex = realIndex.UpperPart;
                if (firstindex > _CachePages.Count) {
                    return default(T);
                }
                T[] page = _CachePages[firstindex];
                return page[realIndex.LowerPart];
            }
            set {
                IndexParts realIndex = new IndexParts() {
                    FullValue = index
                };
                int firstindex = realIndex.UpperPart;
                T[] page = null;
                if (firstindex > _CachePages.Count) {
                    while (firstindex > _CachePages.Capacity) {
                        _CachePages.Capacity = _CachePages.Capacity * 2;
                    }
                    while (firstindex == _CachePages.Count) {
                        _CachePages.Add(null);
                    }
                    page = new T[65536];
                    _CachePages.Add(page);
                } else {
                    page = _CachePages[firstindex];
                    if (page == null) {
                        page = new T[65536];
                        _CachePages[firstindex] = page;
                    }
                }
                page[realIndex.LowerPart] = value;
            }
        }

        [StructLayout(LayoutKind.Explicit)]
        struct IndexParts {

            [FieldOffset(0)]
            internal int FullValue;

            [FieldOffset(0)]
            internal ushort LowerPart;

            [FieldOffset(2)]
            internal ushort UpperPart;

        }

    }
}
